--
-- Author: shineflag
-- Date: 2017-09-05 14:54:15
--
local skynet = require "skynet"
local log = require "log"
local proto = require("json_proto")
local cluster = require("skynet.cluster")
local utils = require("utils")
local json = require("json")

local lobby_conf_fname = "etc/conf/lobby_conf.lua"

--大厅场配置
local lobby_keys={
	name="string",
	ante="number",
	min_carry="number",
	max_carry="number",
	default_buy="number",
	bettime="number",
	seatnum="number",
}

local levels = {}   --所有的场次

local CMD = {}
local CLIENT = {} --客户端传过来的命令


local conf = {
	--        --场次      名称        前注    最小携带         最大携带            下注时间     座位数    
	-- [1] = {lv = 1, name="初级场", ante=0, min_carry=200, 	max_carry=500,  	bettime=15, seatnum=6,},
	-- [2] = {lv = 2, name="中级场", ante=0, min_carry=1000,	max_carry=2500, 	bettime=15, seatnum=6,},
	-- [3] = {lv = 3, name="高级场", ante=0, min_carry=8000,	max_carry=20000,	bettime=15, seatnum=6,},
}

local cur_max_lv = 0



local function create_tablekeeper(cconf)
	if levels[cconf.lv] then
		log.e(TAG,"level [%d] exists",cconf.lv)
	else
		local tablemanger = skynet.newservice "lobby/tablemanager"

		local keeper = {
			tnum = 0,
			player = 0,
			watcher = 0,
			manager = tablemanger
		}
		for key, v in pairs(cconf) do 
			keeper[key] = v 
		end
		levels[cconf.lv] = keeper
		if cconf.lv > cur_max_lv then 
			cur_max_lv = cconf.lv 
		end
		skynet.call(tablemanger,"lua","init",skynet.self(), cconf)
	end
end

--call by client
--用户获取当前的大厅场次配置
function CMD.info(mid, data)
	local pkg = proto.unpack_body(data)
	local chan = pkg.req.chan

	local ver,lvids  = get_chan_ids(chan)
	local lvs = {}
	for _, lv in ipairs(lvids) do 
		if levels[lv] then 
			table.insert(lvs, levels[lv])
		else
			log.e(TAG,"not found lobby lv[%d]",lv)
		end
	end
	return proto.create_resp("lobby.info",{ret=200, ver=ver, levels=lvs})
end

-- call by useragent
-- 查询一个桌子的 handler
function CMD.query_table(lv, tid)
	local keeper = levels[lv]
	return skynet.call(keeper.manager, "lua", "query_table", tid)
end


-- call by client 
-- 匹配一个桌号来进行游戏
function CMD.search(mid, data )
	local pkg = proto.unpack_body(data)
	local lv = pkg.req.lv 
	local old_tid = pkg.req.old_tid
	local keeper = levels[lv]
	if keeper then
		return skynet.call(keeper.manager,"lua","change",mid, old_tid )
	else
		log.e(TAG,"bad lv[%d]",lv)
	end
end

--获取各场次的人数  lv:相应场次 0代表所有场次 call by admin
function CMD.get_players_info(lv)
	local result = {}
	if lv == 0 then 
		for lv , keeper in pairs(levels) do 
			table.insert(result,{lv=lv,tnum=keeper.tnum, player=keeper.player, watcher=keeper.watcher})
		end
	else
		local keeper = levels[lv]
		if keeper then 
			table.insert(result,{lv=lv,tnum=keeper.tnum, player=keeper.player, watcher=keeper.watcher})
		end
	end
	return result
end


----获取指定人数的桌子 --robot
function CMD.get_num_tables(lv, num)
	local result = {}
	if lv == 0 then 
		for lv , keeper in pairs(levels) do 
			local list = skynet.call(keeper.manager, "lua", "query_num_tables",num)
			result[lv] = list
		end
	else
		local keeper = levels[lv]
		if keeper then 
			local list = skynet.call(keeper.manager, "lua", "query_num_tables",num)
			result[lv] = list
		end
	end
	return result
end

-- call by lobby cluster 
-- 当一个大厅桌游戏启动后上报
function CMD.report_lobby_group(group,sname)
	log.d(TAG,"report_lobby_group group[%s] sname[%s]",group, sname)
	for lv , keeper in pairs(levels) do 
		skynet.call(keeper.manager, "lua", "report_lobby_group",group,sname)
	end
end


---------------------大厅场的管理 call by amdin -------------
--获取所有的大厅场
function CMD.getallcashs(data, crypt)
	return proto.create_resp("lobby.getallcashs",{ret=200, levels=conf}, crypt)
end

--新增 大厅场
function CMD.addcashs(data, crypt)
	log.d(TAG,"add new cash[%s]",json.encode(data))
	local resp = {ret=200}
	local new_cash = {}
	for k,v in pairs(cash_keys) do 
		if data[k] and type(data[k]) == v then 
			new_cash[k] = data[k]
		else
			resp.ret = -101
			log.e(TAG,"k[%s] v[%s] is not type %s",k, data[k], type(data[k]))
			break 
		end
	end
	if resp.ret == 200 then 
		cur_max_lv = cur_max_lv + 1
		new_cash.lv = cur_max_lv
		conf[cur_max_lv] = new_cash 
		resp.levels=conf 

		--将配置信息保存到文件
		utils.dump_conf(cash_conf_fname, conf)
		create_tablekeeper(new_cash)
	end
	return proto.create_resp("lobby.addcashs",resp, crypt)
end

function CMD.modifycash(data, crypt)
	log.d(TAG,"modify cash[%s]",json.encode(data))
	local resp = {ret=200}
	if data.lv and conf[data.lv] then 
		local lv = data.lv 
		local mcash = {}
		data.lv = nil 
		for k, v in pairs(data) do 
			if cash_keys[k] and type(v) == cash_keys[k] then 
				mcash[k] = v 
			else
				log.e(TAG,"data error k[%s] or type v[%s] ",k, type(v))
				resp.ret = -101
				break
			end
		end
		if resp.ret == 200 then 
			log.e(TAG,"success modify cash lv[%d] mcash[%s]",lv, json.encode(mcash))
			local cash = conf[lv]
			for k, v in pairs(mcash) do 
				cash[k] = v
			end
			resp.levels = conf 
			utils.dump_conf(cash_conf_fname, conf)
			report_change_cash(lv, cash)
		end
	else
		resp.ret = -101 
	end

	return proto.create_resp("lobby.modifycash",resp, crypt)
end


local function init()
	conf = require("lobby_conf")
	for _, v in pairs(conf) do 
		create_tablekeeper(v)
	end
end

skynet.start(function()
	skynet.dispatch("lua", function(session,source,cmd, subcmd, ...)
		log.d(TAG,"recv cmd[%s]",cmd)
		local f 
		if cmd == "client" then 
			f = assert(CLIENT[subcmd], "not found client cmd " .. subcmd)
			skynet.ret(skynet.pack(f(...)))
		else
			f = assert(CMD[subcmd], "not found cmd " .. subcmd)
			if session ~= 0 then
				skynet.ret(skynet.pack(f(...)))
			else
				f( ... )
			end
		end
	end)
	cluster.register("lobby")
	init()
end)